﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Ymatou.ServiceCenter
{
    /// <summary>
    /// 守护线程
    /// </summary>
    public static class DaemonThread
    {
        private static readonly List<Thread> ThreadList = new List<Thread>();
        private static bool _disposed;

        /// <summary>
        /// 运行一个新的守护线程
        /// </summary>
        /// <param name="executeAction">执行动作</param>
        /// <param name="exceptionAction">发生异常时执行的动作</param>
        /// <param name="sleep">休眠时间</param>
        /// <param name="isBackground">是否为后台线程</param>
        public static void Run(Action executeAction, Action<Exception> exceptionAction, TimeSpan sleep, bool isBackground = true)
        {
            Thread thread = new Thread(() =>
            {
                while (!_disposed)
                {
                    try
                    {
                        if (executeAction != null)
                            executeAction();
                    }
                    catch (Exception ex)
                    {
                        try
                        {
                            if (exceptionAction != null)
                                exceptionAction(ex);
                        }
                        catch
                        {
                            // ignored
                        }
                    }
                    finally
                    {
                        if (sleep.TotalMilliseconds > 0)
                        {
                            Thread.Sleep(sleep);
                        }
                        else
                        {
                            Thread.Sleep(10000);
                        }
                    }
                }
            }) { IsBackground = isBackground };
            thread.Start();
            ThreadList.Add(thread);
        }

        /// <summary>
        /// 运行一个新的守护线程
        /// </summary>
        /// <param name="executeAction">执行动作</param>
        /// <param name="exceptionAction">发生异常时执行的动作</param>
        /// <param name="sleepFunc">返回休眠时间的方法</param>
        /// <param name="isBackground">是否为后台线程</param>
        public static void Run(Action executeAction, Action<Exception> exceptionAction, Func<TimeSpan> sleepFunc , bool isBackground = true)
        {
            if (sleepFunc == null)
                sleepFunc = () => new TimeSpan(0, 0, 5, 0);
            Thread thread = new Thread(() =>
            {
                while (!_disposed)
                {
                    try
                    {
                        if (executeAction != null)
                            executeAction();
                    }
                    catch (Exception ex)
                    {
                        try
                        {
                            if (exceptionAction != null)
                                exceptionAction(ex);
                        }
                        catch
                        {
                            // ignored
                        }
                    }
                    finally
                    {
                        if (sleepFunc().TotalMilliseconds > 0)
                        {
                            Thread.Sleep(sleepFunc());
                        }
                        else
                        {
                            Thread.Sleep(10000);
                        }
                    }
                }
            }) { IsBackground = isBackground };
            thread.Start();
            ThreadList.Add(thread);
        }
        /// <summary>
        /// 释放当前正在执行的守护线程
        /// </summary>
        public static void Dispose()
        {
            try
            {
                _disposed = true;
                if (ThreadList != null && ThreadList.Count > 0)
                {
                    for (int i = 0; i < ThreadList.Count; i++)
                    {
                        ThreadList[i].Abort();
                    }
                    ThreadList.Clear();
                }
            }
            catch
            {
                // ignored
            }
        }
    }
}
